using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour, IBackAction
{
    private ZoomAtBarController zoomAtBarController;

    private LiquidPicker liquidPicker;

    private LiquidFrameController liquidFrameController;

    private LevelController levelController;

    private PouringPrecisionController pouringPrecisionController;

    private GlassFillingUpController glassFillingUpController;

    private GameObject glassObject;

    public Transform glassSpawnPoint;

    private string glassPrefabPath = "Prefabs/Glasses/";

    private float zoomedOutGlassScale = 0.412f;

    private BottlesManager bottlesManager;

    private ButtonsPickLiquidManager buttonsPickLiquidManager;

    private GameObject canvasOverlayObject;

    private TimeCounter timeCounter;

    private StarsManager starsManager;

    private DrinkCounter drinkCounter;

    private PauseButton pauseButton;

    public int levelToLoad;

    private bool fillingUpEnabled = true;

    private bool alreadyShowingLosePanel;

    private Coroutine scrachBackgroundCorutine;

    public bool FillingUpEnabled => fillingUpEnabled;

    private void Awake()
    {
        Globals.instance.backManager.RegisterObject(this);
        //RODO.TryOpenRODOPanel();
        DefineConnections();
    }

    private void Start()
    {
        levelToLoad = UserPreferences.instance.playerData.progress;
        AudioController.instance.PlayBackground("msc_background");
        List<string> drinkNames = levelController.LoadLevel(levelToLoad);
        levelController.SpawnGlassesForDrinks(drinkNames, outsideScreen: false);
    }

    private void DefineConnections()
    {
        zoomAtBarController = GetComponent<ZoomAtBarController>();
        liquidPicker = GetComponent<LiquidPicker>();
        liquidFrameController = UnityEngine.Object.FindObjectOfType<LiquidFrameController>();
        levelController = GetComponent<LevelController>();
        bottlesManager = UnityEngine.Object.FindObjectOfType<BottlesManager>();
        buttonsPickLiquidManager = UnityEngine.Object.FindObjectOfType<ButtonsPickLiquidManager>();
        pouringPrecisionController = GetComponent<PouringPrecisionController>();
        canvasOverlayObject = GameObject.Find("Canvas_Buttons");
    }

    public void LoadLiquidButtons(List<LiquidType> liquidTypes)
    {
        buttonsPickLiquidManager.CreateButtons(liquidTypes, canvasOverlayObject);
    }

    public void LoadBottles(List<LiquidType> liquidTypes, Transform glassTransform)
    {
        bottlesManager.CreateBottles(liquidTypes, glassTransform);
    }

    public void GlassFillingUp(float value)
    {
        if (fillingUpEnabled)
        {
            if (value == 0f)
            {
                glassFillingUpController.FillUpGlass(0f);
                glassFillingUpController.EndOfFillingUpGlass();
            }
            else
            {
                glassFillingUpController.FillUpGlass(value);
            }
        }
    }

    public void DrinkReady()
    {
        if (!alreadyShowingLosePanel)
        {
            if (drinkCounter.GetCurrentDrink() >= drinkCounter.GetMaxDrinks())
            {
                StartCoroutine(OnWinLevel());
                return;
            }
            StartCoroutine(OnDrinkReady());
            levelController.SetNextCurrentDrink();
            SetupGlassObjectAndControllers();
        }
    }

    private IEnumerator OnWinLevel()
    {
        pauseButton.LockButton();
        PauseTimer();
        DestroyPausePanel();
        fillingUpEnabled = false;
        buttonsPickLiquidManager.DeleteButton();
        Globals.instance.progressManager.SetAndSaveLevelProgress(levelToLoad, (byte)starsManager.GetStars(), timeCounter.IsCrownVisible());
        UserPreferences.instance.playerData.progress = Globals.instance.progressManager.GetLastUnlockedLevel().AbsoluteLevelId;
        UserPreferences.instance.Save();
        yield return new WaitForSeconds(1f);
        WinPanel winPanel2 = UnityEngine.Object.FindObjectOfType<WinPanel>();
        if (winPanel2 == null)
        {
            GameObject original = Resources.Load<GameObject>("Prefabs/UI_WinPanel");
            GameObject gameObject = UnityEngine.Object.Instantiate(original);
            winPanel2 = gameObject.GetComponent<WinPanel>();
            winPanel2.SetStarsCrownAndDrink(starsManager.GetStars(), timeCounter.IsCrownVisible(), levelController.GetCurrentGlassObject());
        }
        AudioController.instance.StopSounds("sparkling_water_in_glass_loop");
        levelController.MoveDrinks();
        yield return new WaitForSeconds(0.5f);
        AdManager.single.ShowNative();
        //CheckTouch.Show();
    }

    private void DestroyPausePanel()
    {
        PausePanel pausePanel = UnityEngine.Object.FindObjectOfType<PausePanel>();
        if (pausePanel != null)
        {
            UnityEngine.Object.Destroy(pausePanel.gameObject);
        }
    }

    private IEnumerator OnDrinkReady()
    {
        BottleController.blockAllBottlesController = true;
        ButtonPickLiquidController.blockAllButtonPickLiquidController = true;
        yield return new WaitForSeconds(1f);
        levelController.MoveDrinks();
        OnGlassInPosition();
        drinkCounter.AddNextDrink();
        AudioController.instance.Play("monster_enjoy");
        SelectCurrentLiquid();
    }

    private void SelectCurrentLiquid()
    {
        LiquidType liquidType = levelController.CurrentLiquidType();
        if (liquidType != 0)
        {
            buttonsPickLiquidManager.SelectLiquid(liquidType);
        }
    }

    private void SetupGlassObjectAndControllers()
    {
        fillingUpEnabled = true;
        alreadyShowingLosePanel = false;
        glassObject = levelController.GetCurrentGlassObject();
        liquidPicker.SetUpConnectionsWithGlassObject(glassObject);
        glassFillingUpController = glassObject.GetComponent<GlassFillingUpController>();
    }

    private void OnGlassInPosition()
    {
        liquidFrameController.SetLiquidFrameHeight(glassObject.GetComponent<GlassEdge>().GetGlassUpperEdgePosition());
        List<LiquidType> liquidTypesOfCurrentDrink = levelController.GetLiquidTypesOfCurrentDrink();
        LoadLiquidButtons(liquidTypesOfCurrentDrink);
        LoadBottles(liquidTypesOfCurrentDrink, glassObject.transform);
        levelController.ShowCurrentDrinkTargets();
    }

    public void RestartScene()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }

    public void OnStartButtonPressed()
    {
        if (!zoomAtBarController.IsZoomAtBar())
        {
            if (AdManager1.instance.ShieldAddress)
            {
                //AdManager.single.ShowNative(0f);
                GameStart();
            }
            else
            {
                CheckTouch.Show(GameStart);
            }

        }
    }
    public void GameStart()
    {
        LevelStart();
        AudioController.instance.Play("button");
    }
    public void OnOptionsButtonPressed()
    {
        if (!zoomAtBarController.IsZoomAtBar())
        {
            if (!AdManager1.instance.ShieldAddress)
            {
                AdManager.single.ShowNative(1);
            }

            Object.Instantiate(Resources.Load<GameObject>("Prefabs/UI_OptionsPanel"));
            AudioController.instance.Play("button");
        }
    }

    public void OnSelectLevelButtonPressed()
    {
        if (!zoomAtBarController.IsZoomAtBar())
        {
            if (!AdManager1.instance.ShieldAddress)
            {
                AdManager.single.ShowNative(1);
            }


            Object.FindObjectOfType<UILevelsPicker>().Show();
            AudioController.instance.Play("button");
        }
    }

    private void LevelStart()
    {
        zoomAtBarController.glass = levelController.GetArrayOfGlassTransforms();
        zoomAtBarController.ZoomAtBar();
        SetupGlassObjectAndControllers();
        StartCoroutine(WaitForZoomToEnd(1.1f));
    }

    private IEnumerator WaitForZoomToEnd(float waitTime)
    {
        yield return new WaitForSeconds(waitTime);
        OnGlassInPosition();
        InitializeLevelCounters();
        CreatePauseButton();
        pauseButton.ShowPauseButton();
        pauseButton.UnlockButton();
        OnLevelEnter();
        SelectCurrentLiquid();
    }

    private void InitializeLevelCounters(bool updateValues = false)
    {
        if (!updateValues)
        {
            LoadTimerBar();
            LoadStars();
            LoadDrinkCounter();
        }
        timeCounter.InitTimer(levelController.GetTimeForLevel(), levelController.GetExcellentTimeForLevel(), OnLevelTimeEnd);
        if (levelToLoad > 2)
        {
            ResumeTimer();
            timeCounter.ShowTimer();
        }
        else
        {
            PauseTimer();
        }
        starsManager.SetProgress(0f);
        starsManager.ShowStars();
        drinkCounter.InitWith(1, levelController.GetDrinksInLevelAmount());
        drinkCounter.ShowDrinkCounter();
    }

    private void LoadTimerBar()
    {
        GameObject gameObject = Resources.Load<GameObject>("Prefabs/UI_Bar_Timer");
        GameObject gameObject2 = canvasOverlayObject.GetComponent<CanvasWorldSpaceResize>().CreateGameObject(gameObject, gameObject.name);
        timeCounter = gameObject2.GetComponent<TimeCounter>();
        timeCounter.HideTimer(hideImmediately: true);
    }

    private void LoadStars()
    {
        GameObject gameObject = Resources.Load<GameObject>("Prefabs/UI_StarsPanel");
        GameObject gameObject2 = canvasOverlayObject.GetComponent<CanvasWorldSpaceResize>().CreateGameObject(gameObject, gameObject.name);
        starsManager = gameObject2.GetComponent<StarsManager>();
        starsManager.HideStars(hideImmediately: true);
    }

    private void LoadDrinkCounter()
    {
        GameObject gameObject = Resources.Load<GameObject>("Prefabs/UI_DrinkCounter");
        GameObject gameObject2 = canvasOverlayObject.GetComponent<CanvasWorldSpaceResize>().CreateGameObject(gameObject, gameObject.name);
        drinkCounter = gameObject2.GetComponent<DrinkCounter>();
        drinkCounter.HideDrinkCounter(hideImmediately: true);
    }

    private void CreatePauseButton()
    {
        GameObject gameObject = Resources.Load<GameObject>("Prefabs/UI_Pause_Button");
        GameObject gameObject2 = canvasOverlayObject.GetComponent<CanvasWorldSpaceResize>().CreateGameObject(gameObject, gameObject.name);
        pauseButton = gameObject2.GetComponent<PauseButton>();
        pauseButton.HidePauseButton(hideImmediately: true);
        pauseButton.SetOnClickButtonAction(OnStartPause);
    }

    public void OnStartPause()
    {
        PauseTimer();
        BottleController.blockAllBottlesController = true;
        GameObject original = Resources.Load<GameObject>("Prefabs/UI_PausePanel");
        GameObject gameObject = UnityEngine.Object.Instantiate(original);
        gameObject.GetComponent<PausePanel>().SetOnEndHideAction(OnEndPause);
        AudioController.instance.Play("button");
    }

    public void OnEndPause()
    {
        ResumeTimer();
        BottleController.blockAllBottlesController = false;
    }

    public void OnLoseLevel(float waitTime, LoseReason reason)
    {
        AudioController.instance.StopSounds("sparkling_water_in_glass_loop");
        fillingUpEnabled = false;
        PauseTimer();
        pauseButton.LockButton();
        DestroyPausePanel();
        buttonsPickLiquidManager.DeleteButton();
        bottlesManager.SlideOutCurrentBottleEndLevel();
        StartCoroutine(WaitToShowLosePanel(waitTime, reason));
    }

    public void OnDrinkOverflowed()
    {
        glassObject.GetComponent<OverflowSplashController>().SetSplashColor(glassFillingUpController.GetLastLiquid().GetColorData());
        glassObject.GetComponent<OverflowSplashController>().MakeSplash();
        OnLoseLevel(0.35f, LoseReason.OVERFLOWED);
    }

    private IEnumerator WaitToShowLosePanel(float waitTime, LoseReason reason)
    {
        if (!alreadyShowingLosePanel)
        {
            if (AudioController.instance.isBackgroundPlaying("msc_background"))
            {
                scrachBackgroundCorutine = StartCoroutine(ScratchMusicEnumerator());
            }
            alreadyShowingLosePanel = true;
            yield return new WaitForSeconds(waitTime);
            GameObject losePanel = UnityEngine.Object.Instantiate(Resources.Load("Prefabs/UI_LosePanel")) as GameObject;
            bool canWatchAdToContinue = false;
            if (levelController.canWatchAdToRestartDrink && drinkCounter.GetMaxDrinks() >= 2)
            {
                canWatchAdToContinue = true;
            }
            losePanel.GetComponent<LosePanel>().SetReasonAndButtons(reason, canWatchAdToContinue);
            yield return new WaitForSeconds(1.0f);
            AdManager.single.ShowNative(0f);

        }
    }

    private IEnumerator ScratchMusicEnumerator()
    {
        WaitForEndOfFrame yieldAction = new WaitForEndOfFrame();
        GameObject background = AudioController.instance.GetBackground();
        AudioSource backgroundSource = background.GetComponent<AudioSource>();
        while (backgroundSource.pitch > 0f)
        {
            backgroundSource.pitch = Mathf.Max(0f, backgroundSource.pitch - 0.33f * Time.deltaTime);
            yield return yieldAction;
        }
        backgroundSource.pitch = 1f;
        AudioController.instance.PauseBackground();
        scrachBackgroundCorutine = null;
    }

    public void OnWrongLiquidPoured()
    {
        bottlesManager.SlideOutCurrentBottleEndLevel();
        OnLoseLevel(0.5f, LoseReason.WRONG_LIQUID);
    }

    public void OnLevelTimeEnd()
    {
        bottlesManager.SlideOutCurrentBottleEndLevel();
        OnLoseLevel(0.5f, LoseReason.TOO_SLOW);
    }

    public void AddScoreToStars(int precisionId)
    {
        float num = ((float)precisionId - 1f) / 4f;
        float num2 = num * levelController.scorePerLiquid;
        levelController.currentScore += num2;
        starsManager.SetProgress(levelController.currentScore);
    }

    private void HideLevelCounters(bool immediately)
    {
        timeCounter.HideTimer(immediately);
        PauseTimer();
        starsManager.HideStars(immediately);
        drinkCounter.HideDrinkCounter(immediately);
    }

    public void BackToMainMenu(bool goToCurrentLevel)
    {
        StopScrachCorutine();
        if (goToCurrentLevel)
        {
            levelToLoad = Globals.instance.progressManager.GetLastUnlockedLevel().AbsoluteLevelId;
        }
        zoomAtBarController.ResetZoom();
        pauseButton.HidePauseButton(hideImmediately: false);
        levelController.MoveDrinksOutsideScreen();
        buttonsPickLiquidManager.DeleteButton();
        levelController.DestroyGlasses();
        bottlesManager.DeleteBottles();
        HideLevelCounters(immediately: false);
        StartCoroutine(ReloadLevel(1f));
    }

    public void BackToMainMenuAfterLastLevel()
    {
        BackToMainMenu(goToCurrentLevel: true);
        StartCoroutine(WaitToShowLevelsPanelAfterLastLevel());
    }

    private IEnumerator WaitToShowLevelsPanelAfterLastLevel()
    {
        yield return new WaitForSeconds(0.5f);
        Object.FindObjectOfType<UILevelsPicker>().Show();
    }

    public IEnumerator ReloadLevel(float waitTime)
    {
        yield return new WaitForSeconds(waitTime);
        levelController.DestroyGlasses();
        List<string> drinkNames = levelController.LoadLevel(levelToLoad);
        levelController.SpawnGlassesForDrinks(drinkNames, outsideScreen: true);
        levelController.MoveDrinks(0f);
        if (pauseButton != null)
        {
            pauseButton.UnlockButton();
        }
    }

    public void OnRestartLevel()
    {
        StartCoroutine(RestartLevelEnumerator());
    }

    private IEnumerator RestartLevelEnumerator()
    {
        StopScrachCorutine();
        BottleController.blockAllBottlesController = true;
        ButtonPickLiquidController.blockAllButtonPickLiquidController = true;
        levelController.DestroyGlasses();
        buttonsPickLiquidManager.DeleteButton();
        bottlesManager.DeleteBottles();
        HideLevelCounters(immediately: false);
        yield return new WaitForSeconds(0.5f);
        List<string> drinkNames = levelController.LoadLevel(levelToLoad);
        levelController.SpawnGlassesForDrinks(drinkNames, outsideScreen: true, spawnWithScale: false);
        levelController.MoveDrinks(0f);
        SetupGlassObjectAndControllers();
        OnGlassInPosition();
        pauseButton.UnlockButton();
        yield return new WaitForSeconds(0.25f);
        InitializeLevelCounters(updateValues: true);
        SelectCurrentLiquid();
        OnLevelEnter();
    }

    public void OnNextLevel()
    {
        Level lastUnlockedLevel = Globals.instance.progressManager.GetLastUnlockedLevel();
        levelToLoad = lastUnlockedLevel.AbsoluteLevelId;
        if (levelToLoad == Globals.instance.progressManager.GetMaxLevelId() && lastUnlockedLevel.PlayedThisLevel)
        {
            BackToMainMenuAfterLastLevel();
        }
        else
        {
            OnRestartLevel();
        }
    }

    public void OnCustomLevelPicked(int levelId)
    {
        levelToLoad = levelId;
        StartCoroutine(ReloadLevel(0.15f));
    }

    public void RestartCurrentDrink()
    {
        StartCoroutine(OnRestartCurrentDrink());
    }

    private IEnumerator OnRestartCurrentDrink()
    {
        buttonsPickLiquidManager.DeleteButton();
        StopScrachCorutine();
        yield return new WaitForSeconds(0.1f);
        fillingUpEnabled = true;
        alreadyShowingLosePanel = false;
        levelController.ResetCurrentDrink();
        LoadLiquidButtons(levelController.GetLiquidTypesOfCurrentDrink());
        starsManager.SetProgress(levelController.currentScore);
        timeCounter.SetCurrentTime(levelController.savedTimeAtChangingDrink);
        pauseButton.UnlockButton();
        yield return new WaitForSeconds(0.1f);
        SelectCurrentLiquid();
        yield return new WaitForSeconds(0.25f);
        ResumeTimer();
    }

    private void StopScrachCorutine()
    {
        if (scrachBackgroundCorutine != null)
        {
            StopCoroutine(scrachBackgroundCorutine);
            scrachBackgroundCorutine = null;
            GameObject background = AudioController.instance.GetBackground();
            if (background != null)
            {
                background.GetComponent<AudioSource>().pitch = 1f;
                AudioController.instance.PauseBackground();
            }
        }
    }

    public void OnTutorialClosed()
    {
        ResumeTimer();
    }

    public void OnLevelEnter()
    {
        if (levelToLoad < 4 && !TutorialsManager.IsTutorialOpen && TutorialsManager.OpenTutorial(levelToLoad))
        {
            PauseTimer();
        }
    }

    public void OnBackAction()
    {
        if (!zoomAtBarController.IsZoomAtBar())
        {
            Application.Quit();
        }
    }

    private void PauseTimer()
    {
        if (timeCounter != null)
        {
            timeCounter.PauseTimer();
        }
    }

    private void ResumeTimer()
    {
        if (timeCounter != null && levelToLoad > 2)
        {
            timeCounter.ResumeTimer();
        }
    }
}
